"""
Seaborn relplot 分面图示例

知识点：
1. relplot 的基本用法（kind='scatter' 和 'line'）
2. 使用 col 参数创建列分面
3. 使用 row 参数创建行分面
4. 使用 col_wrap 控制子图布局
5. 调整子图大小和宽高比
6. 组合分面和 hue 进行多维度分析
"""

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# 先设置 seaborn 主题
sns.set_theme(style="ticks")

# 然后强制设置中文字体（必须在 set_theme 之后）
plt.rcParams['font.sans-serif'] = ['PingFang HK', 'Hiragino Sans GB', 'STHeiti', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'

# 创建综合数据集：不同城市、不同季节的温度和降雨量
np.random.seed(42)
cities = ['北京', '上海', '广州', '成都']
seasons = ['春季', '夏季', '秋季', '冬季']
months = list(range(1, 13))

data_list = []
for city in cities:
    for month in months:
        season = seasons[(month - 1) // 3]
        # 模拟温度数据
        base_temp = {'北京': 12, '上海': 16, '广州': 22, '成都': 16}[city]
        seasonal_temp = 15 * np.sin((month - 1) * np.pi / 6)
        temp = base_temp + seasonal_temp + np.random.normal(0, 2)
        
        # 模拟降雨量数据
        base_rain = {'北京': 50, '上海': 100, '广州': 150, '成都': 80}[city]
        seasonal_rain = 50 * np.sin((month - 4) * np.pi / 6)
        rain = max(0, base_rain + seasonal_rain + np.random.normal(0, 20))
        
        data_list.append({
            '城市': city,
            '月份': month,
            '季节': season,
            '温度(°C)': temp,
            '降雨量(mm)': rain,
            '湿度(%)': 50 + rain / 5 + np.random.normal(0, 5)
        })

df = pd.DataFrame(data_list)

# 示例1: 使用 col 参数按城市分面（散点图）
print("=" * 60)
print("示例1: 按城市分面的散点图")
print("=" * 60)

g1 = sns.relplot(
    data=df,
    x='温度(°C)',
    y='降雨量(mm)',
    col='城市',  # 按城市创建列分面
    hue='季节',  # 用颜色区分季节
    kind='scatter',  # 散点图
    height=4,  # 每个子图高度
    aspect=1,  # 宽高比
    palette='Set2',
    s=100,
    alpha=0.7
)
g1.fig.suptitle('不同城市的温度与降雨量关系（按季节分类）', y=1.02, fontsize=14, fontweight='bold')
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/3-1-relplot_col分面.png', 
            dpi=300, bbox_inches='tight')
plt.show()

# 示例2: 使用 row 和 col 创建网格分面
print("\n" + "=" * 60)
print("示例2: 行列网格分面")
print("=" * 60)

# 只选择两个城市和两个季节以简化展示
df_subset = df[df['城市'].isin(['北京', '上海']) & df['季节'].isin(['夏季', '冬季'])]

g2 = sns.relplot(
    data=df_subset,
    x='月份',
    y='温度(°C)',
    row='季节',  # 按季节创建行分面
    col='城市',  # 按城市创建列分面
    kind='line',  # 折线图
    height=3,
    aspect=1.5,
    markers=True,
    marker='o',
    linewidth=2.5,
    ci=None
)
g2.fig.suptitle('不同城市不同季节的温度变化', y=1.02, fontsize=14, fontweight='bold')
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/3-2-relplot_row_col分面.png', 
            dpi=300, bbox_inches='tight')
plt.show()

# 示例3: 使用 col_wrap 控制布局
print("\n" + "=" * 60)
print("示例3: 使用 col_wrap 控制每行显示的子图数量")
print("=" * 60)

g3 = sns.relplot(
    data=df,
    x='月份',
    y='降雨量(mm)',
    col='城市',
    col_wrap=2,  # 每行显示2个子图
    kind='line',
    height=3.5,
    aspect=1.3,
    hue='城市',
    style='城市',
    markers=True,
    dashes=False,
    linewidth=2,
    ci='sd'  # 显示标准差
)
g3.fig.suptitle('各城市月度降雨量变化（含标准差）', y=1.01, fontsize=14, fontweight='bold')
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/3-3-relplot_col_wrap.png', 
            dpi=300, bbox_inches='tight')
plt.show()

# 示例4: 组合多个维度进行复杂分析
print("\n" + "=" * 60)
print("示例4: 多维度综合分析")
print("=" * 60)

g4 = sns.relplot(
    data=df,
    x='温度(°C)',
    y='湿度(%)',
    col='季节',  # 按季节分面
    hue='城市',  # 用颜色区分城市
    size='降雨量(mm)',  # 用大小表示降雨量
    kind='scatter',
    height=4,
    aspect=1,
    sizes=(50, 400),
    alpha=0.6,
    palette='husl'
)
g4.fig.suptitle('温度、湿度、降雨量的季节性关系分析', y=1.01, fontsize=14, fontweight='bold')
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/3-4-relplot_多维度.png', 
            dpi=300, bbox_inches='tight')
plt.show()

# 示例5: 对比 scatter 和 line 两种 kind
print("\n" + "=" * 60)
print("示例5: 同一数据的不同展示方式")
print("=" * 60)

# 创建一个figure包含两种kind的对比
fig = plt.figure(figsize=(16, 6))

# 散点图版本
plt.subplot(1, 2, 1)
city_data = df[df['城市'] == '北京']
sns.scatterplot(
    data=city_data,
    x='温度(°C)',
    y='降雨量(mm)',
    hue='季节',
    size='湿度(%)',
    sizes=(50, 300),
    alpha=0.7,
    palette='Set1'
)
plt.title('散点图：北京温度与降雨量关系', fontsize=12, fontweight='bold')

# 折线图版本
plt.subplot(1, 2, 2)
sns.lineplot(
    data=city_data,
    x='月份',
    y='降雨量(mm)',
    hue='季节',
    markers=True,
    marker='o',
    markersize=8,
    linewidth=2.5,
    ci=None
)
plt.title('折线图：北京月度降雨量变化', fontsize=12, fontweight='bold')

plt.tight_layout()
plt.savefig('/Users/binming/Desktop/CodeBase/python/Python语法/1-常用库/1-数据分析/Seaborn关系图示例/3-5-scatter_vs_line.png', 
            dpi=300, bbox_inches='tight')
plt.show()

print("\n" + "=" * 60)
print("relplot 核心参数说明：")
print("=" * 60)
print("kind        : 图表类型 ('scatter' 或 'line')")
print("col         : 按列创建分面的变量")
print("row         : 按行创建分面的变量")
print("col_wrap    : 每行显示的子图数量")
print("height      : 每个子图的高度（英寸）")
print("aspect      : 宽高比（宽度 = height * aspect）")
print("hue         : 用颜色区分类别")
print("size        : 用大小表示数值")
print("style       : 用样式区分类别")
print("palette     : 调色板")
print("=" * 60)
print(f"\n数据集信息:")
print(f"  总记录数: {len(df)}")
print(f"  城市数量: {df['城市'].nunique()}")
print(f"  季节数量: {df['季节'].nunique()}")
print(f"  温度范围: {df['温度(°C)'].min():.1f}°C - {df['温度(°C)'].max():.1f}°C")
print(f"  降雨量范围: {df['降雨量(mm)'].min():.1f}mm - {df['降雨量(mm)'].max():.1f}mm")
